home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / aros / source / exec / tasks / src / addtask.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  4.3 KB  |  168 lines

  1. /*
  2.     $Id: addtask.c 1.1 1995/12/17 21:37:10 digulla Exp digulla $
  3.     $Log: addtask.c $
  4.  * Revision 1.1  1995/12/17  21:37:10  digulla
  5.  * Initial revision
  6.  *
  7.     Desc:
  8.     Lang: english
  9. */
  10. #include "exec_intern.h"
  11. #include <aros/machine.h>
  12.  
  13. static void KillCurrentTask(void);
  14. void TrapHandler(void);
  15.  
  16. /*****************************************************************************
  17.  
  18.     NAME */
  19.     #include <clib/exec_protos.h>
  20.  
  21.     __AROS_LH3(APTR, AddTask,
  22.  
  23. /*  SYNOPSIS */
  24.     __AROS_LA(struct Task *, task, A1),
  25.     __AROS_LA(APTR         , initPC, A2),
  26.     __AROS_LA(APTR         , finalPC, A3),
  27.  
  28. /*  LOCATION */
  29.     struct ExecBase *, SysBase, 47, Exec)
  30.  
  31. /*  FUNCTION
  32.     Add a new task to the system. If the new task has the highest
  33.     priority of all and task switches are allowed it will be started
  34.     immediately.
  35.     Certain task fields should be intitialized and a stack must be
  36.     allocated before calling this function. tc_SPReg will be used as the
  37.     starting location for the stack pointer, i.e. a part of the stack can
  38.     be reserved to pass the task some initial arguments.
  39.     Memory can be added to the tc_MemEntry list and will be freed when the
  40.     task dies. The new task's registers are set to 0.
  41.  
  42.     INPUTS
  43.     task      - Pointer to task structure.
  44.     initPC      - Entry point for the new task.
  45.     finalPC   - Routine that is called if the initPC() function returns.
  46.             A NULL pointer installs the default finalizer.
  47.  
  48.     RESULT
  49.     The address of the new task or NULL if the operation failed (can only
  50.     happen with TF_ETASK set - currenty not implemented).
  51.  
  52.     NOTES
  53.  
  54.     EXAMPLE
  55.  
  56.     BUGS
  57.  
  58.     SEE ALSO
  59.     RemTask()
  60.  
  61.     INTERNALS
  62.  
  63.     HISTORY
  64.     29-10-95    digulla automatically created from
  65.                 exec_lib.fd and clib/exec_protos.h
  66.     17-12-95    digulla Incorporated code by Matthias Fleischner
  67.  
  68. *****************************************************************************/
  69. {
  70.     __AROS_FUNC_INIT
  71.     APTR sp;
  72.  
  73.     /* Set node type to NT_TASK if not set to something else. */
  74.     if(!task->tc_Node.ln_Type)
  75.     task->tc_Node.ln_Type=NT_TASK;
  76.  
  77.     /* Sigh - you should provide a name for your task. */
  78.     if(task->tc_Node.ln_Name==NULL)
  79.     task->tc_Node.ln_Name="unknown task";
  80.  
  81.     /* Signals default to all system signals allocated. */
  82.     if(task->tc_SigAlloc==0)
  83.     task->tc_SigAlloc=0xffff;
  84.  
  85.     /* Currently only used for segmentation violation */
  86.     if(task->tc_TrapCode==NULL)
  87.     task->tc_TrapCode = (APTR)TrapHandler;
  88.  
  89.     /* Get new stackpointer. */
  90.     sp=task->tc_SPReg;
  91.     if(task->tc_SPReg==NULL)
  92. #if STACK_GROWS_DOWNWARDS
  93.     sp=(UBYTE *)task->tc_SPUpper-SP_OFFSET;
  94. #else
  95.     sp=(UBYTE *)task->tc_SPLower-SP_OFFSET;
  96. #endif
  97.  
  98.     /* Default finalizer? */
  99.     if(finalPC==NULL)
  100.     finalPC = (APTR)KillCurrentTask;
  101.  
  102.     /* Init new context. */
  103.     sp=PrepareContext(sp,initPC,finalPC);
  104.  
  105.     /* store sp */
  106.     task->tc_SPReg=sp;
  107.  
  108.     /* Set the task flags for switch and launch. */
  109.     if(task->tc_Switch)
  110.     task->tc_Flags|=TF_SWITCH;
  111.  
  112.     if(task->tc_Launch)
  113.     task->tc_Flags|=TF_LAUNCH;
  114.  
  115.     /* tc_MemEntry _must_ already be set. */
  116.  
  117.     /*
  118.     Protect the task lists. This must be done with Disable() because
  119.     of Signal() which is usable from interrupts and may change those
  120.     lists.
  121.      */
  122.     Disable();
  123.  
  124.     /* Add the new task to the ready list. */
  125.     task->tc_State=TS_READY;
  126.     Enqueue(&SysBase->TaskReady,&task->tc_Node);
  127.  
  128.     /*
  129.     Determine if a task switch is necessary. (If the new task has a
  130.     higher priority than the current one and the current one
  131.     is still active.) If the current task isn't of type TS_RUN it
  132.     is already gone.
  133.     */
  134.     if(task->tc_Node.ln_Pri>SysBase->ThisTask->tc_Node.ln_Pri&&
  135.        SysBase->ThisTask->tc_State==TS_RUN)
  136.     {
  137.     /* Are taskswitches allowed? (Don't count own Disable() here) */
  138.     if(SysBase->TDNestCnt>=0||SysBase->IDNestCnt>0)
  139.         /* No. Store it for later. */
  140.         SysBase->AttnResched|=0x80;
  141.     else
  142.     {
  143.         /* Switches are allowed. Move the current task away. */
  144.         SysBase->ThisTask->tc_State=TS_READY;
  145.         Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  146.  
  147.         /* And force a rescedule. */
  148.         Switch();
  149.     }
  150.     }
  151.  
  152.     Enable();
  153.  
  154.     return task;
  155.     __AROS_FUNC_EXIT
  156. } /* AddTask */
  157.  
  158.  
  159. /* Default finalizer. */
  160. static void KillCurrentTask (void)
  161. {
  162.     /* I need the global SysBase variable here - there's no local way to get it. */
  163.     extern struct ExecBase *SysBase;
  164.  
  165.     /* Get rid of current task. */
  166.     RemTask(SysBase->ThisTask);
  167. }
  168.